Skip to content

Conversation

@JimmyWang6
Copy link
Contributor

see: KAFKA-19817
This PR intended to move DynamicTopicClusterQuotaPublisher to the metadata module .
To prevent circular dependencies, several associated classes have been migrated as well,including ClientSensors , ClientQuotaMetadataManager, ThrottleCallback and ThrottledChannel.
Additionally, a new interface QuotaManagersProvider has been introduced to avoid the need to move class QuotaManagers in QuotaFactory, as doing so would have necessitated significantly more extensive changes.

@github-actions github-actions bot added triage PRs from the community core Kafka Broker kraft labels Oct 28, 2025
@JimmyWang6 JimmyWang6 marked this pull request as draft October 28, 2025 11:37
@JimmyWang6 JimmyWang6 marked this pull request as ready for review October 28, 2025 12:13
@chia7712
Copy link
Member

> Task :server-common:checkstyleMain
[ant:checkstyle] [ERROR] /home/chia7712/project/kafka/server-common/src/main/java/org/apache/kafka/server/quota/ClientQuotaManager.java:34:1: Disallowed import - org.apache.kafka.server.network.Session. [ImportControl]
[ant:checkstyle] [ERROR] /home/chia7712/project/kafka/server-common/src/main/java/org/apache/kafka/server/quota/ClientQuotaManager.java:35:1: Disallowed import - org.apache.kafka.server.util.ShutdownableThread. [ImportControl]

@JimmyWang6 please fix the build error

@JimmyWang6
Copy link
Contributor Author

@chia7712 Thanks for the comment, just fixed the build error, please take another look when you're free :)

Copy link
Member

@chia7712 chia7712 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JimmyWang6 thanks for this patch!

@github-actions github-actions bot removed the triage PRs from the community label Oct 31, 2025
@JimmyWang6
Copy link
Contributor Author

@chia7712 Thanks for your comments. All of them have been addressed, and please take another look.

@JimmyWang6 JimmyWang6 requested a review from chia7712 October 31, 2025 07:05
quotaManagersProvider.clientQuotaCallbackPlugin().ifPresent(plugin -> {
if (delta.topicsDelta() != null || delta.clusterDelta() != null) {
Cluster cluster = MetadataCache.toCluster(clusterId, newImage);
if (plugin.get().updateClusterMetadata(cluster)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The necessity of this method is being discussed in KIP-1200. While I hope the vote succeeds, there is no harm in migrating the code though

int nodeId,
FaultHandler faultHandler,
String nodeType,
QuotaManagersProvider quotaManagers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you consider de-coupling those components by using lambda function? for example:

    public DynamicTopicClusterQuotaPublisher(
        String clusterId,
        int nodeId,
        FaultHandler faultHandler,
        String nodeType,
        Plugin<ClientQuotaCallback> clientQuotaCallbackPlugin,
        Runnable updateQuotaMetricConfigs
    ) {
        this.clusterId = clusterId;
        this.nodeId = nodeId;
        this.faultHandler = faultHandler;
        this.nodeType = nodeType;
        this.clientQuotaCallbackPlugin = clientQuotaCallbackPlugin;
        this.updateQuotaMetricConfigs = updateQuotaMetricConfigs;
    }

    @Override
    public String name() {
        return "DynamicTopicClusterQuotaPublisher " + nodeType + " id=" + nodeId;
    }

    @Override
    public void onMetadataUpdate(MetadataDelta delta, MetadataImage newImage, LoaderManifest manifest) {
        try {
            if (delta.topicsDelta() != null || delta.clusterDelta() != null) {
                Cluster cluster = MetadataCache.toCluster(clusterId, newImage);
                if (clientQuotaCallbackPlugin.get().updateClusterMetadata(cluster)) {
                    updateQuotaMetricConfigs.run();
                }
            }
        } catch (Exception e) {
            String deltaName = "MetadataDelta up to " + newImage.highestOffsetAndEpoch().offset();
            faultHandler.handleFault("Uncaught exception while publishing dynamic topic or cluster changes from " + deltaName, e);
        }
    }
  1. we could create DynamicTopicClusterQuotaPublisher only if the clientQuotaCallbackPlugin is existent
  2. we wrap all callbacks in a single runnable object to avoid move many classes into server-common module

@JimmyWang6 WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @chia7712 ,
I just tried and found that clientQuotaCallbackPlugin also belongs to class ClientQuotaManager, so if we are going to de-coupe those components, the code will be shown like this:

public class DynamicTopicClusterQuotaPublisher implements MetadataPublisher {
    private final FaultHandler faultHandler;
    private final String nodeType;
    private final Runnable updateQuotaMetricConfigs;

    public DynamicTopicClusterQuotaPublisher(
        FaultHandler faultHandler,
        String nodeType,
        Runnable updateQuotaMetricConfigs
    ) {
        this.faultHandler = faultHandler;
        this.nodeType = nodeType;
        this.updateQuotaMetricConfigs = updateQuotaMetricConfigs;
    }

    @Override
    public String name() {
        return "DynamicTopicClusterQuotaPublisher " + nodeType;
    }

    @Override
    public void onMetadataUpdate(MetadataDelta delta, MetadataImage newImage, LoaderManifest manifest) {
        try {
            if (delta.topicsDelta() != null || delta.clusterDelta() != null) {
                updateQuotaMetricConfigs.run();
            }
        } catch (Exception e) {
            String deltaName = "MetadataDelta up to " + newImage.highestOffsetAndEpoch().offset();
            faultHandler.handleFault("Uncaught exception while publishing dynamic topic or cluster changes from " + deltaName, e);
        }
    }
}

And the logic of the original DynamicTopicClusterQuotaPublisher will still remain in the new class updateQuotaMetricConfigs somewhere within the core module. However, such a modification might deviate from the original intent of this issue. What's your perspective on this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes but DynamicTopicClusterQuotaPublisher can generate the Cluster and check the result of updateClusterMetadata

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants